/*
 *  The dev.h header file defines some functions to manage the Devices file system
 */

#ifndef _DEV_H
#define _DEV_H

#include <types.h>
#include <linkedlist.h>

#include <bus.h>

// Max length of a device name
#define DEV_NAME_MAX_LENGTH  64

// Major numbers for devices
#define DEV_MAJOR_BUS             0x0010
#define DEV_MAJOR_TTY             0x0020
#define DEV_MAJOR_HDD_IDE         0x0100
#define DEV_MAJOR_HDD_CD          0x0110
#define DEV_MAJOR_HDD_SCSI        0x0120
#define DEV_MAJOR_HDD_TAPE        0x0130
#define DEV_MAJOR_NET_LOOP        0x0200
#define DEV_MAJOR_NET_ETHER       0x0210

// Device flags
// used in the "flags" field of the dev_device structure
#define DEV_FLG_BLOCK   0x00000000
#define DEV_FLG_CHAR    0x00000001
// device can be read
#define DEV_FLG_READ    0x00000002
// device can be written
#define DEV_FLG_WRITE   0x00000004
// meta operations (read/write) supported
#define DEV_FLG_META    0x00000008

// Device error codes
#define DEV_ERR_NONE          0      /* no error, correct result */
#define DEV_ERR_NOT_FOUND     1      /* device not found */
#define DEV_ERR_OVERWRITE     2      /* trying to overwrite existing device */

struct dev_interface {
  int (*vfs_open)(int *fd, char *path, int mode);
  int (*vfs_close)(int *fd);
  int (*vfs_read)(int fd, void *buf, size_t count);
  int (*vfs_write)(int fd, void *buf, size_t count);
  int (*vfs_meta_read)(int fd, char *key, void *value, size_t count);
  int (*vfs_meta_write)(int fd, char *key, void *value, size_t count);
};

struct dev_meta_info {
  char *key;
  void *value;  
  dword_t size;
};

struct dev_device {
  dword_t major;
  dword_t minor;
  char name[DEV_NAME_MAX_LENGTH];
  dword_t flags;
  dword_t state;
  struct dev_interface *interface;
  ptr_list_t meta_info;
  struct bus_type *bus;
};

extern void dev_initialize(void);
extern int dev_add_bus(struct bus_type *bus);
extern int dev_add_device(struct dev_device *device);
extern int dev_find_device(char *name,struct dev_device **device);
extern void dev_print_list(void);

#endif /* _DEV_H */
